<template>
	<view class="createCont" :style="{ height: webStyle.height }">
		<view class="bg"></view>
		<view class="title-box" :style="{ 'padding-top': inf0Pt + 'vh' }">
			<image class="back" @click="back" :src="imgPath + 'AICont/back-arrow.svg'" mode="widthFix"></image>
			<view class="title">生成文案</view>
			<view class="back"></view>
		</view>
		<view class="main">
			<view class="h1">
				{{ h1_text }}
			</view>
			<view class="contView1" v-if="0">
				<view class="contViewTitle">
					<view class="text">参考文献</view>
				</view>
				<view class="literature">
					<view class="item" v-for="(item, index) in literature" :key="index">
						<view class="text">{{ item.text }}</view>
					</view>
				</view>
			</view>
			<view class="contView2">
				<view class="contViewTitle">
					<view class="text">生成文稿</view>
				</view>
				<view class="tips">文稿基于热点生成，点击可以编辑。</view>
				<view class="aiCont">
					<scroll-view scroll-y="true" class="scroll-textarea" :scroll-top="scrollHeight">
						<textarea :adjust-position="false" class="textarea" ref="scrollTextarea" placeholder="请输入文案" :auto-height="true" name="aiCont" id="" @input="contentWatch" :maxlength="2000" :value="aiCont.cont"></textarea>
					</scroll-view>
				</view>
				<view class="tips" style="text-align: center; margin-top: 2vw">热点来自于AI推荐，请您自行核查详情内容</view>
			</view>
			<view class="contView3" v-if="0">
				<view class="contViewTitle">
					<view class="text">参考标题</view>
				</view>
				<view class="titleList">
					<view class="item" v-for="(item, index) in contList" :key="index" @tap="toCreateCont(item, index)">
						<view class="dot" :style="{ background: item.dot }"></view>
						<view class="cont">{{ item.cont }}</view>
					</view>
				</view>
			</view>
		</view>

		<view class="f">
			<view class="submit" @tap="copy(aiCont.cont)">{{ "复制内容" }}</view>
			<view class="submit" @tap="useCont" :style="{ filter: aiCont.cont ? 'brightness(1)' : 'brightness(0.5)' }">{{ submitBtnText }}</view>
			<view class="submit" @tap="changeCont" :style="{ filter: aiCont.cont ? 'brightness(1)' : 'brightness(0.5)' }">{{ "智能改稿" }}</view>
		</view>
		<LoginDialog ref="LoginDialog" :show="LoginDialogShow" @successFn="loginDialogShowSucc" @changeShow="changeLoginDialogShow" style="z-index: 999"></LoginDialog>
	</view>
</template>

<script>
import { tools } from "@/utils/util.js";
import myRequest, * as request from "@/utils/api.js";
import * as api from "@/api/createVideo.js";
// import { fetchEventSource } from "@microsoft/fetch-event-source";

let contentWatchTimer = null;
let iptTimer = null;
let chatTimer = null;
let dataList = []; // 保存数据流
let renderStart = false; // 开始渲染数据
let getDataEnd = false; // 获取流数据结束
let iterator = null; // 获取数据流迭代器

export default {
	name: "createCont",
	data() {
		return {
			imgPath: tools.imgPath,
			inf0Pt: 0,
			systemInfo: {},
			webStyle: {
				height: ""
			},
			LoginDialogShow: false,
			requestTask: null,
			scrollHeight: 0,
			chatTimer: false,
			pageInfo: {},
			h1_text: "",
			submitBtnText: "去创作",
			literature: [
				{
					text: "撰写一封保险投诉举报信时，应当确保信件内容清晰、客观、具体，并遵循正式的书写格式。以下是一个投诉举报信的基本模板，您可以根据实际情况进行调整"
				},
				{
					text: "撰写一封保险投诉举报信时，应当确保信件内容清晰、客观、具体，并遵循正式的书写格式。以下是一个投诉举报信的基本模板，您可以根据实际情况进行调整"
				},
				{
					text: "撰写一封保险投诉举报信时，应当确保信件内容清晰、客观、具体，并遵循正式的书写格式。以下是一个投诉举报信的基本模板，您可以根据实际情况进行调整"
				}
			],
			contList: [
				{
					cont: "是什么突然让你放弃一段感情",
					dot: "#ff0000"
				},
				{
					cont: "经常用耳机的3个60原则",
					dot: "#f3ad33"
				},
				{
					cont: "是什么突然让你放弃一段感情",
					dot: "#00997f"
				},
				{
					cont: "韩国记者画熊猫仿妆哽咽告别福宝",
					dot: ""
				},
				{
					cont: "快递新规下的驿站",
					dot: ""
				},
				{
					cont: "是什么突然让你放弃一段感情",
					dot: ""
				},
				{
					cont: "经常用耳机的3个60原则",
					dot: ""
				},
				{
					cont: "韩国记者画熊猫仿妆哽咽告别福宝",
					dot: ""
				},
				{
					cont: "快递新规下的驿站",
					dot: ""
				}
			],
			aiCont: {
				cont: ""
			}
		};
	},
	methods: {
		// 获取系统info
		initSystemInfo(isUpdate = true) {
			const that = this;
			return new Promise((resolve, reject) => {
				uni.getSystemInfo({
					success(payload) {
						if (isUpdate) {
							that.systemInfo = payload;
							that.webStyle.height = `${that.systemInfo.windowHeight}px`;
							console.log("initSystemInfo", that.systemInfo);
							switch (that.systemInfo.uniPlatform) {
								case "web":
									that.inf0Pt = 4.5;
									break;
								case "app":
									that.inf0Pt = 4.5;
									break;
								case "mp-weixin":
									that.inf0Pt = 4.5;
									break;
							}
						}
						resolve(payload);
					}
				});
			});
		},
		// 跳转页面
		toPage(path, type = "navigateTo") {
			uni[type]({
				url: path
			});
		},
		// 回退
		back() {
			let pages = getCurrentPages();
			if (pages.length > 1) {
				uni.navigateBack({
					delta: 1
				});
			} else {
				uni.setStorageSync("toHome", {
					footerBarListAc: 1
				});
				uni.reLaunch({
					url: "/pages/index/index"
				});
			}
		},
		// 获取页面参数
		initPageInfo(opt) {
			let pageInfo = uni.getStorageSync("createContInfo");
			this.pageInfo = pageInfo;
			this.h1_text = pageInfo.h1_text;
			uni.removeStorageSync("createContInfo");
		},
		// 监听登录弹出层显示
		changeLoginDialogShow(val) {
			this.LoginDialogShow = val;
		},
		// 登陆成功数据刷新
		loginDialogShowSucc() {
			this.getData();
		},
		// 获取数据
		async getData() {
			if (this.pageInfo.sourceId) {
				this.getCont();
			}
		},
		// 文案改变
		contentWatch(e) {
			if (contentWatchTimer) {
				clearTimeout(contentWatchTimer);
			}
			contentWatchTimer = setTimeout(async () => {
				contentWatchTimer = null;
				this.aiCont.cont = e.detail.value;
			}, 688);
		},
		// AI文案改写
		changeCont() {
			let option = {
				url: "https://ai.yainoo.com/api/aiwork/chat/chat_streamv8",
				method: "POST",
				data: {
					agentId: "1811635099264049154",
					userInput: "{[" + this.aiCont.cont + "]}" + "\n\n根据以上{[]}内的信息, 生成一次改稿内容，开头和结尾不要出现提示话术，不要副标题，不要出现小红书字样"
				}
			};
			this.getCont(option);
		},
		// 获取AI热门文案
		async getCont(option) {
			if (this.chatTimer) return false;
			const that = this;
			// 防止误触
			that.chatTimer = chatTimer = true;
			option =
				option && option.url && option.method
					? option
					: {
							url: "https://ai.yainoo.com/api/aiwork/chat/chat_news",
							// url: "http://192.168.124.87:3000/stream",
							// url: "https://ai.yainoo.com/api/aiwork/chat/chat_streamv8",
							method: "POST",
							data: this.pageInfo.sourceId
							// data: {
							// 	agentId: "1811636375162937346",
							// 	userInput: "你好啊"
							// },
					  };

			// 渲染流程开始
			console.log("渲染流程开始~");
			let resList = await new Promise(async (resolve) => {
				dataList = []; // 保存数据流
				renderStart = false; // 开始渲染数据
				getDataEnd = false; // 获取流数据结束
				iterator = dataList[Symbol.iterator](); // 获取数据流迭代器

				// 渲染数据流
				const renderFn = async (iteratorItem, currInd, aaa) => {
					// 缓存当前渲染索引
					let newInd = currInd;
					// 缓存数据列表
					let tempList = JSON.parse(JSON.stringify(dataList));

					if (!iteratorItem.value.isRender) {
						// 表示此数据已渲染(下面是渲染过程)
						iteratorItem.value.isRender = true;

						// 渲染过程=========
						// 获取渲染索引 (用来逐字渲染时从该索引位置渲染)
						currInd = currInd || that.aiCont.cont.length;

						// 逐字展示实现,更新当前渲染索引
						newInd = await that.showTextLoop(that.aiCont, that.aiCont.cont + iteratorItem.value.text, currInd);
						// 渲染过程结束======
					}

					// 获取后端数据流索引（用来判断当前渲染状态）
					let dataInd = tempList.findIndex((e) => e.id == iteratorItem.value.id);

					if (dataInd == tempList.length - 1) {
						// 这里表示数据列表渲染完成，等待新的后端数据返回，轮询时间为0.15秒
						await new Promise((sleep) => setTimeout(sleep, 150));

						// 递归结束,后端数据已全部获取，数据渲染也全部完成
						// console.log("递归结束,后端数据已全部获取", {newInd, getDataEnd, dataInd, dataList,tempList});
						if (newInd == -1 || (dataList.length == tempList.length && getDataEnd)) {
							console.log("渲染流程结束！");
							chatTimer = null;
							that.chatTimer = false;
							that.submitBtnText = "去创作";
							return true;
						}

						// 重新等待
						return renderFn(iteratorItem, newInd, "111");
					} else {
						// 这里表示数据列表未完成，执行下一个数据渲染
						return renderFn(iterator.next(), newInd, "222");
					}
				};

				// 开始发送数据
				const token = uni.getStorageSync("token") || uni.getStorageSync("_token");
				uni.showLoading({
					title: "热点文案生成中..."
				});
				that.submitBtnText = "文案生成中";

				// #ifndef MP-WEIXIN
				// const postData = {
				// 	// 参数
				// 	tenant_id: 'BIZ',
				// 	card_id: '584415218126295040'
				// }
				// let xhr = new XMLHttpRequest()
				// xhr.open('POST', url, true)
				// xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8')
				// xhr.onprogress = function () {
				//   console.log('流式输出', xhr.responseText)
				// }
				// xhr.onloadend = function () {
				//   console.log('done')
				// }
				// xhr.send(JSON.stringify(postData))
				// return;
				let wsState = "close";
				let wsId = tools.createID();
				let ws = uni.connectSocket({
					url: "ws://175.178.252.101/ws",
					header: {
						Authorization: token,
						"content-type": "application/json"
					},
					// protocols: ["protocol1"],
					multiple: true,
					method: "GET",
					success(res) {
						console.log("ws-succ", res);
					},
					fail(err) {
						uni.hideLoading();
						console.log("ws-fail", err);
					},
					complete() {}
				});
				ws.onOpen((res) => {
					console.log("ws-onOpen", res);
					ws.send({
						data: JSON.stringify({
							msgType: "addUser",
							msgCont: {
								userId: wsId,
								token: token
							}
						})
					});
					wsState = "open";
				});
				ws.onError((err) => {
					console.log("ws-onError", err);
					getDataEnd = true; // 获取流数据结束
					wsState = "close";
				});
				ws.onClose((res) => {
					console.log("ws-onClose", res);
					getDataEnd = true; // 获取流数据结束
					wsState = "close";
				});
				ws.onMessage((res) => {
					// console.log("ws-onMessage", res, res.data);
					if (res.data == "addSuccess") {
						console.log("发起请求！");
						ws.send({
							data: JSON.stringify({
								msgType: "proxy-request",
								msgCont: {
									header: {
										Authorization: token,
										"Content-Type": "application/json",
										Accept: "text/event-stream"
										// Accept: "application/json, text/plain, */*"
									},
									...option
								}
							})
						});
					} else {
						let msgData = JSON.parse(res.data);
						switch (msgData.msgType) {
							case "dataItem":
								console.log(msgData.msgCont);
								// 修改数据体
								let resObj = {
									id: tools.createID(),
									data: msgData.msgCont,
									// text: text.slice(text.lastIndexOf("data:")).slice(6),
									text: msgData.msgCont.replace(/\\n/g, "\n"),
									isRender: false
								};
								dataList.push(resObj);
								console.log("resObj:", resObj);
								if (!renderStart) {
									uni.hideLoading();
									that.aiCont.cont = "";
									renderStart = true; // 开始渲染后端流数据
									let iteratorItem = iterator.next();
									renderFn(iteratorItem);
								}
								break;
							case "end":
								console.log(msgData.msgCont);
								getDataEnd = true; // 获取流数据结束
								ws.close();
								break;
							default:
								break;
						}
					}
				});
				// 将ws应用到全局，方便中断请求
				this.requestTask = ws;
				// #endif

				// #ifdef MP-WEIXIN
				let requestTask = uni.request({
					responseType: "text",
					enableChunked: true, // 开启流传输
					header: {
						// "Content-Type": "application/json",
						// Accept: "text/event-stream",
						Authorization: token
					},
					...option,
					success(res) {
						console.log(res);
						getDataEnd = true; // 获取流数据结束
						// #ifndef MP-WEIXIN
						uni.hideLoading();
						let content = res.data
							.replace(/↵/g, "\n")
							.match(/(data:)?(.*)(\n\n)?/g)
							?.map((e) => {
								if (!e) return "";
								let startInd = 0;
								let endInd = e.length;
								if (/data:/.test(e)) {
									startInd = 5;
								}
								if (/\n\n/.test(e)) {
									endInd = -2;
								}
								let resVal = e.slice(startInd, endInd);
								return resVal.replace(/\\n/g, "\n");
							})
							.join("");
						that.aiCont.cont = content;
						that.submitBtnText = "去创作";
						// #endif
					},
					fail(err) {
						console.log(err);
						chatTimer = null;
						that.chatTimer = false;
						if (err.errMsg != "request:fail abort") {
							tools.easyToast("网络出错!");
							that.aiCont.cont = "网络出错!";
							that.stop();
						} else {
							// tools.easyToast("请求中断!");
						}
						getDataEnd = true; // 获取流数据结束
					}
				});

				// 获取到响应头
				requestTask.onHeadersReceived((res) => {
					console.log(res.header);
					uni.hideLoading();
				});

				// 获取到响应数据
				requestTask.onChunkReceived(async (res) => {
					// arraybuffer转string
					const uint8Array = new Uint8Array(res.data);
					let text = String.fromCharCode.apply(null, uint8Array);
					text = decodeURIComponent(escape(text));

					// 修改数据体
					let resObj = {
						id: tools.createID(),
						data: text,
						// text: text.slice(text.lastIndexOf("data:")).slice(6),
						text: text
							.replace(/↵/g, "\n")
							.match(/(data:)?(.*)(\n\n)?/g)
							?.map((e) => {
								if (!e) return "";
								let startInd = 0;
								let endInd = e.length;
								if (/data:/.test(e)) {
									startInd = 5;
								}
								if (/\n\n/.test(e)) {
									endInd = -2;
								}
								let resVal = e.slice(startInd, endInd);
								return resVal.replace(/\\n/g, "\n");
							})
							.join(""),
						isRender: false
					};
					dataList.push(resObj);
					console.log("resObj:", resObj);
					if (!renderStart) {
						renderStart = true; // 开始渲染后端流数据
						that.aiCont.cont = "";
						let iteratorItem = iterator.next();
						renderFn(iteratorItem);
					}
				});

				// 将requestTask应用到全局，方便中断请求
				this.requestTask = requestTask;
				// #endif
			});
		},
		// 逐字展示效果实现
		showTextLoop(inputEl, text, currInd = 0) {
			let ind = currInd; // 渲染索引
			let renderText = text; // 渲染内容
			return new Promise((next) => {
				let time = tools.randomNum(10, 50); // 设置渲染时间间隔 10~20毫秒
				// #ifdef APP
				time = tools.randomNum(76, 86);
				// #endif
				setTimeout(async () => {
					// 此时可能因为网络问题或者后端服务器奔溃，直接结束流程
					if (!this.chatTimer || !chatTimer) {
						next(-1);
						return -1;
					}

					ind++; // 更新渲染索引
					this.$set(inputEl, "cont", renderText.slice(0, ind)); // 渲染数据

					// textarea滚到底部实现===========
					let selector = "scroll-textarea .textarea";
					// 获取该元素
					let el = await new Promise(async (next) => {
						this.$nextTick(async () => {
							let el = await tools.getNode(uni, "." + selector);
							next(el);
						});
					});

					if (!chatTimer[0]) {
						chatTimer = [el.height, el.height]; // 缓存元素高度
					} else {
						chatTimer[1] = el.height; // 更新元素高度
						// 判断元素高度是否变化，如果变化就重新滚到底部
						if (chatTimer[0] != chatTimer[1]) {
							chatTimer[0] = chatTimer[1];
							this.scrollHeight = chatTimer[0];
						} else {
						}
					}
					// 聊天界面滚到底部实现结束=========

					// 递归结束
					if (ind >= renderText.length) {
						next(ind);
						return ind;
					}

					// 开始下一个字渲染
					let newInd = await this.showTextLoop(inputEl, text, ind);

					// console.log("逐字展示效果实现22", { newInd });
					next(newInd);
					return newInd;
				}, time);
			});
		},
		// 停止渲染
		stop() {
			chatTimer = null;
			this.chatTimer = false;
			getDataEnd = true;
			// #ifdef MP-WEIXIN
			this.requestTask?.abort();
			// #endif
			// #ifndef MP-WEIXIN
			this.requestTask?.close();
			// #endif
		},
		// 复制
		copy(text = "") {
			uni.setClipboardData({
				data: text,
				success() {
					tools.easyToast("复制成功！");
				},
				fail(err) {
					console.log(err);
				}
			});
		},
		// 使用文本
		useCont(item, index) {
			if (this.submitBtnText != "去创作") return;
			uni.setStorageSync("aiCont", {
				updateType: "AiCont",
				cont: this.aiCont.cont
			});
			let pages = getCurrentPages();
			let pageInd = -1;
			switch (this.pageInfo?.toPage) {
				case "index/2": //AI文案
					let [pageName, footerBarListAc] = this.pageInfo.toPage.split("/");
					uni.setStorageSync("toHome", {
						footerBarListAc: footerBarListAc
					});
					pageInd = pages.findIndex((e) => e.route == "pages/index/index");
					if (pageInd != -1) {
						uni.navigateBack({
							delta: pages.length - (pageInd + 1)
						});
					} else {
						uni.reLaunch({
							url: `/pages/${pageName}/${pageName}`
						});
					}
					break;
				default:
					pageInd = pages.findIndex((e) => e.route == "pages/createVideo/createVideo");
					console.log(pageInd, "/pages/createVideo/createVideo", pages);
					if (pageInd != -1) {
						uni.navigateBack({
							delta: pages.length - (pageInd + 1)
						});
					} else {
						this.toPage("/pages/createVideo/createVideo", "reLaunch");
					}
					break;
			}
		}
	},
	onLoad(opt) {
		this.initSystemInfo();
		this.initPageInfo(opt);
		this.getData();
	},
	onUnload() {
		// this.stop();
	},
	beforeDestroy() {
		this.stop();
	}
};
</script>

<style lang="scss">
::-webkit-scrollbar {
	width: 0vw !important;
	height: 0vw !important;
	display: none;
}

.createCont {
	width: 100vw;
	// height: 100vh;
	background: #0c1411;
	position: relative;
	color: #fff;
	padding: 0vw 3vw;
	box-sizing: border-box;
	display: flex;
	flex-direction: column;

	.bg {
		position: fixed;
		width: 100%;
		height: 100%;
		top: 0;
		left: 0;
		background: radial-gradient(#034748 0%, #010c1f 100%);
	}

	.title-box {
		display: flex;
		justify-content: space-between;
		align-items: center;
		box-sizing: border-box;
		position: relative;
		.back {
			width: 6vw;
		}

		.title {
			font-size: 36rpx;
			font-weight: 400;
			color: rgba(255, 255, 255, 1);
		}
	}
	.main {
		flex: 1;
		overflow: auto;
		display: flex;
		flex-direction: column;
	}
	.h1 {
		// text-align: center;
		font-size: 6.8vw;
		font-weight: 700;
		margin: 8.6vw 0vw;
		position: relative;
	}
	.contViewTitle {
		display: flex;
		margin: 2vw 0vw;
		.text {
			font-size: 4.6vw;
		}
	}
	.contView1 {
		position: relative;
		margin-bottom: 8.6vw;
		width: 100%;
		.literature {
			width: 100%;
			display: -webkit-box;
			overflow: auto;
			.item {
				width: 48.6%;
				margin-right: 2%;
				box-sizing: border-box;
				padding: 3vw;
				border-radius: 2.5vw;
				background: rgba(255, 255, 255, 0.068);
				.text {
					width: 100%;
					font-size: 3.86vw;
					overflow: hidden;
					display: -webkit-box; /* 将对象作为弹性伸缩盒子模型显示 */
					-webkit-line-clamp: 2; /* 行数，值可以改，表示展示X行后多余的缩略展示 */
					-webkit-box-orient: vertical; /* 设置或检索伸缩盒对象的子元素的排列方式 */
					word-break: break-all;
				}
			}
		}
	}

	.contView2 {
		display: flex;
		flex-direction: column;
		position: relative;
		margin-bottom: 8.6vw;
		width: 100%;
		.tips {
			font-size: 4vw;
			color: rgba(255, 255, 255, 0.5);
			margin-bottom: 2.2vw;
		}
		.aiCont {
			height: 52vh;
			width: 100%;
			background: rgba(255, 255, 255, 0.068);
			border-radius: 2.5vw;
			box-sizing: border-box;
			padding: 3vw;
			overflow: auto;
			.scroll-textarea {
				width: 100%;
				height: 100%;
				.textarea {
					display: block;
					width: 100%;
					// height: 100%;
					font-size: 4.6vw;
					line-height: 20px;
				}
			}
		}
	}
	.contView3 {
		position: relative;
		margin-bottom: 8.6vw;
		width: 100%;
		.titleList {
			width: 100%;
			.item {
				display: flex;
				align-items: center;
				margin: 6vw;
				margin-left: 0vw;

				.dot {
					width: 2vw;
					height: 2vw;
					margin-right: 2.5vw;
					border-radius: 50%;
					background: rgba(54, 85, 93, 1);
				}

				.cont {
					font-size: 4.6vw;
					font-weight: 400;
					color: rgba(255, 255, 255, 1);
				}
			}
		}
	}

	.f {
		width: 86%;
		margin: 6vw auto;
		box-sizing: border-box;
		// padding: 10vw 0vw;
		position: relative;
		display: flex;
		justify-content: space-between;
		align-items: center;
		.submit {
			width: 30%;
			opacity: 1;
			border-radius: 10px;
			background: rgba(0, 153, 127, 1);
			display: flex;
			justify-content: center;
			align-items: center;
			font-size: 3.6vw;
			font-weight: 500;
			color: rgba(255, 255, 255, 1);
			padding: 2.5vw 0vw;
			margin-bottom: 3vw;
		}
	}
}
</style>
